package org.jnarcissus;

import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.StringDescription;
import org.jbrisk.text.StringUtils;

/**
 * Executes an assert on a {@link MonitoredInstanceMethodCall} instance.
 * 
 * @author Rafael Ribeiro.
 * 
 */
public class MonitoredInstanceMethodCallAssert extends MonitoredInstanceMethodAssertBase {

	private Matcher<?> matcher;
	private String reason;

	public String getReason() {
		return reason;
	}

	public void setReason(String reason) {
		this.reason = reason;
	}

	Matcher<?> getMatcher() {
		return matcher;
	}

	void setMatcher(Matcher<?> matcher) {
		this.matcher = matcher;
	}

	public MonitoredInstanceMethodCallAssert(MonitoredInstanceMethodCall method) {

		super(method);

	}

	void execute() {
		
		execute(true);
	}
	 
	void execute(boolean invokeMethod) throws AssertionError {

		try {

			MonitoredInstanceMethodCall monitoredMethod = getMonitoredMethod();
			
			Object superMethodValue = (invokeMethod) ? monitoredMethod.getMethodProxy().invokeSuper(monitoredMethod.getSource(), monitoredMethod.getArguments()) : monitoredMethod.getLastCallReturnValue();

			if (!matcher.matches(superMethodValue)) {

				Description description = new StringDescription();

				if (!StringUtils.isNullOrEmpty(getReason())) {

					description.appendText(getReason());
					description.appendText(StringUtils.NEW_LINE);
				}

				description.appendText("Called: ");
				monitoredMethod.appendMethodDescription(description);
				description.appendText(StringUtils.NEW_LINE);
				description.appendText("Expected: ");
				description.appendDescriptionOf(matcher);
				description.appendText(StringUtils.NEW_LINE);
				description.appendText("Actual: ");
				description.appendValue(superMethodValue);

				throw new java.lang.AssertionError(description.toString());
			}

		} catch (AssertionError assertionError) {

			throw assertionError;

		} catch (Throwable e) {

			throw new RuntimeException(e);
		}
	}
}
